#include "mediawidget.h"
#include "ui_mediawidget.h"

#include <QDir>
#include <QFileDialog>
#include <QDebug>
#include <QRegularExpression>
#include <QTextCodec>
#include <QMediaMetaData>
#include <QEvent>
#include <QCloseEvent>
#include <QMessageBox>
#include <QMenu>
#include <QSettings>

MediaWidget::MediaWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MediaWidget)
{
    ui->setupUi(this);
    musicMsgMap = new QMap<QString, QMap<QString, QString> *>();
    tableModel = new TableModel();
    lyricLabel = new LyricLabel(this);
    tableWidget = new MusicTableView(this);
    tableWidget->installEventFilter(this);
    tableWidget->setModel(tableModel);
    connect(tableWidget, &MusicTableView::doubleClicked, this, &MediaWidget::playClickedMedia);
    initMediaPlayer();
}

MediaWidget::~MediaWidget()
{
    delete ui;
}

void MediaWidget::initMediaPlayer()
{
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
    setWindowTitle(tr("音乐播放控制器"));
    setWindowIcon(QIcon(":/images/icon.png"));
    setMinimumSize(410, 210);
    setMaximumSize(1920, 1080);
    QSettings settings;

    settings.value("mediaWidget/rect").isNull() ? setGeometry(QRect(400,200,410,210)) : setGeometry(settings.value("mediaWidget/rect").toRect());
    settings.value("mediaWidget/playState").isNull() ? wasPlaying = false : wasPlaying = settings.value("mediaWidget/playState").toBool();


    //设置音乐播放对象
    player = new QMediaPlayer();
    output = new QAudioOutput();
    player->setAudioOutput(output);
//    player->setSource(QUrl::fromLocalFile("C:/Users/Administrator/Documents/QT Code/Qt Improve/build-MyMediaPlayer-Desktop_Qt_6_6_0_MinGW_64_bit-Debug/music/我是明星.mp3"));
    isReady = false;

    //设置桌面轮盘
    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/images/icon.png"));
    trayIcon->setToolTip("PitchMusic播放器");
    QMenu *trayMenu = new QMenu;
    trayMenu->addAction("播放", player, &QMediaPlayer::play);
    trayMenu->addAction("暂停", player, &QMediaPlayer::pause);
    trayMenu->addAction("上一首", this, &MediaWidget::fastBackward);
    trayMenu->addAction("下一首", this, &MediaWidget::fastForward);
    trayMenu->addSeparator();
    trayMenu->addAction("桌面歌词", lyricLabel, &QLabel::show);
    trayMenu->addAction("播放列表", this, &MediaWidget::showMusicListWidget);
    trayMenu->addAction("退出", this, &MediaWidget::quit);
    trayIcon->setContextMenu(trayMenu);
    connect(trayIcon, &QSystemTrayIcon::activated, this, &MediaWidget::activateTrayIcon);
    connect(trayIcon, &QSystemTrayIcon::messageClicked, this, &MediaWidget::show);
    trayIcon->show();

    connect(ui->resourceBtn, &QPushButton::clicked, this, &MediaWidget::openMedia);
    connect(ui->controlBtn, &QPushButton::toggled, this, &MediaWidget::controlMedia);
    connect(ui->resetBtn, &QPushButton::clicked, this, &MediaWidget::resetMedia);
    connect(ui->fastBackBtn, &QPushButton::clicked, this, &MediaWidget::fastBackward);
    connect(ui->fastForwBtn, &QPushButton::clicked, this, &MediaWidget::fastForward);
    connect(ui->silentBtn, &QPushButton::clicked, this, &MediaWidget::silent);
    connect(ui->processSlider, &QSlider::sliderMoved, this, &MediaWidget::mapSliderToPosition);
    connect(ui->volumnSlider, &QSlider::sliderMoved, this, &MediaWidget::changeVolumn);
    connect(player, &QMediaPlayer::positionChanged, this, &MediaWidget::processChanged);
    connect(player, &QMediaPlayer::mediaStatusChanged, this, &MediaWidget::setReady);
    connect(player, &QMediaPlayer::playbackStateChanged, this, &MediaWidget::updateWidget);
    connect(ui->PlBtn, &QPushButton::clicked, this, &MediaWidget::showMusicListWidget);
    connect(ui->LrcBtn, &QPushButton::clicked, lyricLabel, &LyricLabel::show);
    output->setVolume(0.5);
    ui->volumnSlider->setValue(50);

    if(!settings.value("mediaWidget/curMusicPath").isNull()){
        QString fileName = settings.value("mediaWidget/curMusicPath").toUrl().toLocalFile();
        curIndex = tableModel->getIndexByFileName(fileName);
        openMediaByName(fileName);
    }
    if(!settings.value("tableWidget/isVisible").isNull()){
        if(settings.value("tableWidget/isVisible").toBool()) showMusicListWidget();
    }
    if(!settings.value("lyricLabel/isVisible").isNull()){
        if(settings.value("lyricLabel/isVisible").toBool()) lyricLabel->show();
    }
}

void MediaWidget::playClickedMedia(const QModelIndex &index)
{
    qDebug() << index;
    if(index.row() == curIndex.row()){
        resetMedia();
        wasPlaying = true;
        ui->controlBtn->setChecked(true);
        player->play();
        return;
    }
    wasPlaying = true;
    QString fileName = tableModel->getFileNameByIndex(index);
    openMediaByName(fileName);
}

void MediaWidget::openMedia()
{
    isReady = false;

    QString fileName = QFileDialog::getOpenFileName(this, tr("Open Media File"),
                                                    QDir::currentPath(),
                                                    tr("Media (*.mp3)"));

    openMediaByName(fileName);
}

void MediaWidget::openMediaByName(QString fileName)
{
    if(fileName.isEmpty()) return;
    qDebug() << fileName;
    player->setSource(QUrl::fromLocalFile(fileName));
    QMediaMetaData metaData = player->metaData();
    musicMsg = new QMap<QString, QString>();
    if(!metaData.value(QMediaMetaData::Title).toString().isEmpty())
        musicMsg->insert("ti", metaData.value(QMediaMetaData::Title).toString());
    else{
        QList<QString> splitList = fileName.split("/");
        musicMsg->insert("ti", splitList.at(splitList.size() - 1).left(splitList.at(splitList.size() - 1).size() - 4));
    }
    musicMsg->insert("al", metaData.value(QMediaMetaData::ContributingArtist).toString());
    int msec = metaData.value(QMediaMetaData::Duration).toInt();
    QTime time(0, 0);
    time = time.addMSecs(msec);
    musicMsg->insert("len", time.toString("mm:ss"));
    QModelIndex index = tableModel->getIndexByFileName(fileName);
    if(index.row() == -1){ //只在新增时插入
        musicMsgMap->insert(fileName, musicMsg);
        curIndex = tableModel->setMusicMsg(fileName, musicMsg);
    }else{
        curIndex = index;
    }
    QString lyricName = fileName.left(fileName.length() - 4) + ".lrc";
    loadLyric(lyricName);
}

void MediaWidget::loadLyric(QString fileName)
{
    qDebug() << fileName;
    lyric.clear();
    QFile file(fileName);
    if(!file.open(QFile::ReadOnly)){
        lyricLabel->stopTimer();
        lyricLabel->setText("欢迎使用PitchMusic桌面歌词");
        return;
    }
    QTextStream in(&file);
    in.setEncoding(QStringConverter::Utf8); //必须设置，否则中文读取乱码
    while (!in.atEnd()) {
        QString line = in.readLine();
        process_line(line);
    }
}

void MediaWidget::process_line(QString line)
{
//    qDebug() << "line: "<< line;
    QString pattern1 = "\\[(?<key>[a-z]+):(?<value>.*)\\]"; //匹配msg行，如[ti:我是明星]
    QString pattern2 = "\\[(?<min>\\d+):(?<sec>\\d+).(?<tenMsec>\\d+)\\]"; //匹配lyric行，如[01:10.79][00:14.65]
    QRegularExpression re;
    re.setPattern(pattern1);
    QRegularExpressionMatch match = re.match(line);
    if(match.hasMatch()){/*
        qDebug() << "caputured key: "<< match.captured("key") << "caputured value: "<< match.captured("value");*/
        musicMsg->insert(match.captured("key"), match.captured("value"));
    }else{
        re.setPattern(pattern2);
        QRegularExpressionMatchIterator it = re.globalMatch(line);
        int len = 0;
        QList<int> *keyList = new QList<int>();
        while(it.hasNext()){
            QRegularExpressionMatch match = it.next();
            len += match.capturedLength();
            int min = match.captured("min").toInt();
            int sec = match.captured("sec").toInt();
            int tenMsec = match.captured("tenMsec").toInt();
            keyList->append(tenMsec * 10 + sec * 1000 + min * 60 * 1000);
        }
        QString value = line.right(line.length() - len);
        foreach (int key, *keyList) {
//            qDebug() << "caputured key: "<< key << "caputured value: "<< value;
            lyric.insert(key, value);
        }
    }
}

void MediaWidget::fastForward()
{
    playClickedMedia(tableModel->getNextData(curIndex));
}

void MediaWidget::fastBackward()
{
    playClickedMedia(tableModel->getBackData(curIndex));
}

void MediaWidget::controlMedia(bool isPlay)
{
    if(!isReady) {
        ui->controlBtn->setCheckable(false);
        return;
    }
    if(isPlay){
        qDebug() << "播放音乐";
        if(isReady) player->play();
    }else{
        qDebug() << "音乐暂停";
        if(isReady) player->pause();
    }
}

void MediaWidget::resetMedia()
{
    changeProcess(0);
}

void MediaWidget::silent()
{
    ui->volumnSlider->setSliderDown(true);
    ui->volumnSlider->setValue(0);
}

void MediaWidget::changeVolumn(int vol)
{
    output->setVolume(static_cast<float>(vol) / 100.0);
}

void MediaWidget::mapSliderToPosition(float val)
{
    if(isReady){
        changeProcess((val / 100) * player->duration());
    }
}

void MediaWidget::changeProcess(int val)
{
    if(isReady){
        if(val < 0) val = 0;
        if(val > player->duration()) val = player->duration();
        player->setPosition(val);
    }
}

void MediaWidget::processChanged(int val)
{
    //更新三个内容，一个是slider条，一个是processText文本，一个是lyric文本
    if(!ui->processSlider->isSliderDown()){ //当检测到slider正在拖动，此时不应在此处更改slider的位置
        ui->processSlider->setSliderDown(false);
        ui->processSlider->setValue(val * 100 / player->duration());
    }
    updateLyric(val);
    updateProcessText(val);
}



void MediaWidget::updateLyric(int curMsec)
{
    if(!lyric.isEmpty()){
        QMap<int, QString>::iterator it = lyric.upperBound(curMsec); //此时获取的是第一个大于的it(如果不存在，会返回指向end()的指针，end()-1即末尾元素)
        if(lyric.begin() == it){
            ui->lyricText->setText("");
            return;
        }
        int total;
        if(lyric.end() == it){
            total = player->duration() - (it - 1).key();
        }else{
            total = it.key() - (it - 1).key();
        }
        it--; //向前移动1，找到最后一个不大于的it
        if(it.key() == curLyricStartTime) return;
        curLyricStartTime = it.key();
        ui->lyricText->setText(it.value());
        lyricLabel->setText(it.value());
        lyricLabel->setAddWidthByTotal(total);
    }
}

void MediaWidget::updateProcessText(int val)
{
    QTime cur(0, 0);
    cur = cur.addMSecs(val);
    QTime dur(0, 0);
    dur = dur.addMSecs(player->duration());
    ui->processText->setText(tr("%1/%2").arg(cur.toString("mm:ss")).arg(dur.toString("mm:ss")));
}

void MediaWidget::setReady(QMediaPlayer::MediaStatus status)
{
    if(player->mediaStatus() >= QMediaPlayer::LoadedMedia and player->mediaStatus() <= QMediaPlayer::BufferedMedia){
        qDebug() << "音乐资源加载完成"<<"加载状态"<<status << "上次播放状态" << wasPlaying;
        isReady = true;
        ui->controlBtn->setCheckable(true);
        if(wasPlaying)
            ui->controlBtn->setChecked(true);
    }else if(player->mediaStatus() == QMediaPlayer::EndOfMedia){
        qDebug() << "音乐资源播放结束" << "加载状态"<<status;
        playClickedMedia(tableModel->getNextData(curIndex, curType));
    }
    else {
        qDebug() << "音乐资源加载失败" << "加载状态"<<status;
        isReady = false;
        ui->controlBtn->setCheckable(false);
    }
}

void MediaWidget::updateWidget(QMediaPlayer::PlaybackState state)
{
    qDebug() << "当前播放状态 state: "<<state;
    if(state == QMediaPlayer::PlayingState){
        setWindowTitle("正在播放: " + musicMsg->value("ti"));
        wasPlaying = true;
    }else{
        if(state == QMediaPlayer::PausedState) {
            wasPlaying = false;
        }
        setWindowTitle("音乐播放控制器");
    }
}

void MediaWidget::showMusicListWidget()
{
    tableWidget->show();
}

void MediaWidget::quit()
{
    //保存播放记录
    tableModel->saveData();
    writeSettings();
    //关闭其他窗口
    tableWidget->close();
    qApp->quit();
}

bool MediaWidget::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() == QEvent::Close){
        if(obj->metaObject()->className() == QTableView::staticMetaObject.className()){
            // 关闭窗口时执行的清理内容
            tableWidget->hide();
            event->ignore();
        }
    }
    return QWidget::eventFilter(obj, event);
}

void MediaWidget::closeEvent(QCloseEvent *event)
{
    if(isVisible()){
        hide();
        tableWidget->hide();
//        trayIcon->showMessage("PitchMusic播放器", "点我重新进入主界面");
        event->ignore();
    }
}

void MediaWidget::writeSettings()
{
    QSettings settings;
    settings.setValue("mediaWidget/rect", geometry());
    settings.setValue("mediaWidget/playState", player->playbackState() == QMediaPlayer::PlayingState);
    settings.setValue("mediaWidget/curMusicPath", player->source());
    settings.setValue("tableWidget/rect", tableWidget->geometry());
    settings.setValue("tableWidget/isVisible", tableWidget->isVisible());
    settings.setValue("lyricLabel/rect", lyricLabel->geometry());
    settings.setValue("lyricLabel/isVisible", lyricLabel->isVisible());
}

void MediaWidget::activateTrayIcon(QSystemTrayIcon::ActivationReason reason)
{
    if(reason == QSystemTrayIcon::Trigger){
        show();
    }
}


